﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Net.Chirash.Twitter.TweetZone.WindowComponents.Containers;
using Net.Chirash.Twitter.TwitterClient;

namespace Net.Chirash.Twitter.TweetZone.WindowComponents.ViewModels
{
    public class ZoneControllerViewModel
        : IDisposable
    {

        public ZoneControllerViewModel(Type ContainerType, ContainerViewModelBase ViewModel)
        {
            var disposeMethod = new Action<Container>((cnt) =>
                {
                    cnt.ViewModel.UnSubscribe();
                });
            this.Composer = new ContainerComposer(ContainerType, disposeMethod, ViewModel);
            ViewModel.TaskSubscribe();
        }

        public ContainerComposer Composer { get; private set; }

        public string ContainerTitle
        {
            get
            {
                if (Composer != null)
                    return Composer.ContainerViewModel.ToString();
                else
                    return "";
            }
        }

        private ZoneContainerCollection _parent;
        public ZoneContainerCollection Parent
        {
            get
            {
                return _parent;
            }
            set
            {
                if (_parent == value)
                    return;
                else
                {
                    if (_parent != null && _parent.Contains(this))
                        throw new InvalidOperationException("Parentにこのオブジェクトが残っています");

                    var oldval = _parent;
                    _parent = value;

                    OnParentPropertyChanged(oldval, value);
                }
            }
        }

        #region commands

        #region Command CloseContainer
        public ICommand CloseContainer
        {
            get { return new RelayCommand(CloseContainer_Execute, CloseContainer_CanExecute); }
        }

        private void CloseContainer_Execute(object param)
        {
            this._parent.Remove(this);
        }

        private bool CloseContainer_CanExecute(object param)
        {
            return _parent != null;
        }
        #endregion

        #region Command InsertTimelineContainer
        public ICommand InsertTimelineContainer
        {
            get { return new RelayCommand(InsertTimelineContainer_Execute, InsertTimelineContainer_CanExecute); }
        }

        private void InsertTimelineContainer_Execute(object param)
        {
            TimelineTypes type;
            Enum.TryParse<TimelineTypes>(param as string, true, out type);

            var containervm = new TimelineContainerViewModel(type);
            var newvm = new ZoneControllerViewModel(typeof(TimelineContainer), containervm);
            this.Parent.Insert(Parent.IndexOf(this), newvm);

            newvm.Composer.ContainerViewModel.RefreshAsync(null);
        }

        private bool InsertTimelineContainer_CanExecute(object param)
        {
            return _parent != null && param != null && param is string;
        }
        #endregion

        #region Command ErrorReset
        public ICommand ErrorReset
        {
            get { return new RelayCommand(ErrorReset_Execute); }
        }

        private void ErrorReset_Execute(object param)
        {
            Composer.ContainerViewModel.LastErrorMessage.Provider = null;
        }

        #endregion

        #endregion

        #region Events

        public event EventHandler<ParentPropertyChangedEventArgs> ParentPropertyChanged;
        protected void OnParentPropertyChanged(ZoneContainerCollection oldval, ZoneContainerCollection newval)
        {
            if (ParentPropertyChanged != null)
                ParentPropertyChanged(this,
                    new ParentPropertyChangedEventArgs() { OldValue = oldval, NewValue = newval });
        }

        public class ParentPropertyChangedEventArgs
            : EventArgs
        {
            public ZoneContainerCollection OldValue;
            public ZoneContainerCollection NewValue;
        }

        #endregion

        public void Dispose()
        {
            GC.SuppressFinalize(this);
            if (this.Composer != null)
            {
                this.Composer.Dispose();
            }
        }

        ~ZoneControllerViewModel()
        {
            this.Dispose();
        }
    }

    public class ZoneContainerCollection
        : System.Collections.ObjectModel.ObservableCollection<ZoneControllerViewModel>
    {
        public ZoneContainerCollection()
            : base()
        {
            this.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ZoneContainerCollection_CollectionChanged);
        }

        public readonly object LockObject = new object();

        //protected override void InsertItem(int index, ZoneControllerViewModel item)
        //{
        //    Console.WriteLine("insert");
        //    base.InsertItem(index, item);
        //}

        //protected override void MoveItem(int oldIndex, int newIndex)
        //{
        //    Console.WriteLine("moved");
        //    base.MoveItem(oldIndex, newIndex);
        //}

        private void ZoneContainerCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            //Console.WriteLine("ob changed : {0}", Enum.GetName(typeof(System.Collections.Specialized.NotifyCollectionChangedAction), e.Action));
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    if (e.NewItems != null)
                    {
                        foreach (var item in e.NewItems)
                            (item as ZoneControllerViewModel).Parent = this;
                    }
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    if (e.OldItems != null)
                    {
                        foreach (var item in e.OldItems)
                            (item as ZoneControllerViewModel).Parent = null;
                    }
                    break;
            }
        }


        //public override event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;

    }

    public class RelayCommand : ICommand
    {
        #region Fields

        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        #endregion // Fields

        #region Constructors

        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }
        #endregion // Constructors

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        #endregion // ICommand Members
    }
}
